<?php

namespace XWAM\Addon\PXCallSystem\Controller;

/**
 * 外线控制器
 *
 * @author Alen
 * @since 1.0 2014-6-19 by sutroon
 */
class TrunkController extends AppbaseController {

    /**
     * sip表中继前缀
     * @var string tr-peer- 8个字符
     */
    private $trunk_prefix = 'tr-peer-'; // trixbox=9999,freepbx=tr-peer-
    /**
     * sip表中继注册前缀
     * @var string 9999999 7个字符
     */
    private $register_prefix = 'tr-reg-'; // trixbox=9999999,freepbx=tr-reg-

    /**
     * 显示项目列表
     */

    public function index() {
        $this->display();
    }

    public function get_trunk_list_json() {
        $search = I();
        if ($search['tn']) {
            $where['account'] = $search['tn'];
        }
        if ($search['siteID']) {
            $where['siteID'] = $search['siteID'];
        }
        if ($search['host']) {
            $where['host'] = $search['host'];
        }
        if (!$this->isSuperAdmin) {
            $where['siteID'] = $this->loginData['siteID'];
        }
        $data = AddonD('Trunk')->get_trunk_list($where);
        $this->ajaxReturn($data);
    }

    /**
     * 导出数据
     * @since 1.0 <2015-7-2> SoChishun Added.
     */
    public function trunk_export() {
        if (!$this->isSuperAdmin) {
            die('没有权限!');
        }
        $list = AddonD('Trunk')->scope('export')->select();
        if (!$list) {
            $this->ajaxMsg(false, '找不到符合条件的记录!');
        }
        sofn_excel_export($list);
    }

    /**
     * 获取中继列表
     * 返回格式：account, account(regMode|regNumber|username)
     */
    public function get_json() {
        if ($this->isSuperAdmin) {
            if (I('siteID')) {
                $where['siteID'] = I('siteID');
            }
        } else {
            $where['siteID'] = $this->loginData['siteID'];
        }
        $arr = M('tcti_trunk')->where($where)->cache(true)->field(array("account as id", "concat(account,'(',regMode,'|',regNumber,'|',username,')') as text"))->select();
        $this->ajaxReturn($arr);
    }

    /**
     * 显示项目编辑表单
     */
    public function item_edit() {
        $id = I('id');
        if ($id) {
            $this->assign('data', M('tcti_trunk')->find($id));
        }
        $this->display();
    }

    /**
     * 保存项目
     */
    public function item_save() {
        $params = new \Org\Su\Params();
        $params->addParam('siteID', 'number', '租户未选择!');
        $params->addParam('account', 'require', 'account必须填写!');
        $params->addParam('host', 'require', '服务器必须填写!');
        $params->addParam('port', 'number', '端口号必须填写!');
        $params->addParam('regNumber', 'number', '注册数量必须填写!');
        $params->addParam('regMode', 'require', '注册模式必需选择!');
        $params->addParam('nat', 'require', 'nat必须选择!');
        $params->addParam('accountcode', 'require', 'accountcode必须填写!');
        $params->addParam('context', 'require', 'context必须填写!');
        $params->addParam('insecure', 'require', 'insecure必须填写!');
        $params->addParam('dtmfmode', 'require', 'dtmfmode必须选择!');
        $params->addParam('disallow', 'require', 'disallow必须填写!');
        $params->addParam('defaultexpiry', 'number', '注册超时无效');
        $params->addParam('allow', 'require', 'allow必须选择!');
        $regMode = I('regMode');
        if ($regMode == 'register' || $regMode == 'ims') {
            $params->addParam('username', 'require', '认证账户必须填写!');
            $params->addParam('password', 'require', '认证密码必须填写!');
            $params->addParam('fromuser', 'require', 'fromuser必须填写!');
            $params->addParam('type', 'require', 'type必须填写!');
            $params->addParam('fromdomain', 'require', 'fromdomain必须填写!');
            $params->addParam('type', 'require', '类型未选择!');
        } else {
            $params->addData('type', 'friend');
        }
        if ($params->hasError()) {
            $this->ajaxMsg(false, $params->getError());
        }
        $id = I('id');
        $hasId = strlen($id) > 0;
        $account = I('account');
        $M = M('tcti_trunk');
        if ($id) {
            $where['id'] = $id;
            $result = $M->where($where)->save($params->getParams());
        } else {
// 检测用户名是否重复
            $where['account'] = $account;
            if ($M->where($where)->count() > 0) {
                $this->ajaxMsg(false, '[' . $account . '] 已存在!');
            }
            $params->addData('createdTime', date('Y-m-d H:i:s'));
            $result = $M->add($params->getParams());
            $id = $result;
        }
        if ($result === false) {
            $this->ajaxMsg(false, '保存失败!');
        } else {

// 如果是新增用户则自动注册asterisk
            $result = $this->save_asterisk($params->getParams(), $hasId ? 'update' : 'add');
            if ($result === false) {
// 如果注册失败则删除已插入的记录
                $account = I('account');
                $where['account'] = $account;
                $M->where($where)->delete();
                $this->ajaxMsg(false, '更新CTI基础服务失败!');
            } else {
                if ($hasId) {
                    $this->force_need_reload();
                } else {
                    $msg = $this->Activate($params->getParams(), 1);
                    if ($msg === true) {
                        $this->force_need_reload();
                    } else {
                        $this->ajaxMsg(false, $msg);
                    }
                }
            }
        }
        $this->ajaxMsg(true);
    }

    /**
     * 删除项目
     */
    public function item_delete($id = '') {
        if (!$id) {
            $this->ajaxMsg(false, '编号丢失');
        }
        $M = M('tcti_trunk');
        $accounts = $M->where(array('id' => array('in', $id)))->getField('account', true);
        $errs = array();
        foreach ($accounts as $account) {
            $count = M('tcti_task_strategy')->where(array('trunkName' => $account))->count();
            if ($count > 0) {
                $errs[$account] = $count;
            }
        }
        if ($errs) {
            $msg = '';
            foreach ($errs as $key => $n) {
                $msg.='中继 ' . $key . ' 被 ' . $n . ' 个任务策略使用中.'."\n";
            }
            $this->ajaxMsg(false, $msg);
        }
        $result = $M->delete($id);
        if ($result === FALSE) {
            $this->ajaxMsg(false, '删除失败');
        } else {
            // 删除alterisk表数据
            $sip_ids = M('asterisk.sip')->where(array('keyword' => 'account', 'data' => array('in', $accounts)))->getField('id', true);
            foreach ($sip_ids as $sip_id) {
                $id_tmp = substr($sip_id, strlen($this->trunk_prefix));
                if ($id_tmp) {
                    $M->execute("delete from asterisk.sip where id in ('" . $sip_id . "','" . $this->register_prefix . $id_tmp . "');");
                    $M->execute("delete from asterisk.trunks where trunkid='$id_tmp'");
                }
            }
            $this->force_need_reload();
            $this->ajaxMsg(true);
        }
    }

    /**
     * 保存到asterisk数据库
     * @param array $data
     * @param string $mode 模式,add=新增,update=更新
     * @since 1.0 2014-7-4 by sutroon
     */
    function save_asterisk($data, $mode) {
        $a = new \Think\Model\AdvModel();
        $result = $a->patchQuery($this->get_save_asterisk_sql($data, $mode));
        if ($result === false) {
            die($a->getDbError());
        }
        return $result;
    }

    /**
     * 获取注册asterisk的写入语句
     * @param array $data
     * @param string $mode add=新增,update=更新
     * @return array
     */
    protected function get_save_asterisk_sql($data, $mode) {
        $sip = array(
            'account' => $data["account"],
            'disallow' => $data["disallow"], // all
            'type' => $data["type"], // friend
            'nat' => $data["nat"], // no
            'accountcode' => $data["accountcode"],
            'host' => $data["host"],
            'port' => $data["port"],
            'fromdomain' => $data["fromdomain"],
            'username' => $data["username"],
            'secret' => $data["password"],
            'fromuser' => $data["fromuser"],
            'context' => $data["context"], // my-internal
            'insecure' => $data["insecure"], // port,invite
            'dtmfmode' => $data["dtmfmode"], // rfc2833
            'defaultexpiry' => $data['defaultexpiry'], // 注册超时 ims=3600,默认120
            'allow' => str_replace(',', '&', $data["allow"]), // g729&g723&ulaw
            'call-limit' => $data['regNumber'],
        );
        if ('ip' == $data['regMode']) {
            // ip模式去掉两个字段
            unset($sip['fromdomain']);
            unset($sip['username']);
            unset($sip['password']);
            unset($sip['fromuser']);
            unset($sip['secret']);
            unset($sip['insecure']);
        }
        $arr = array();
        $prefixlen = strlen($this->trunk_prefix);
        if ($mode == 'update') {
            $n = M('asterisk.sip')->where("keyword='account' and data='" . $data["account"] . "'")->getField(array('substring(id,' . $prefixlen . '+1) as a'));
            foreach ($sip as $k => $v) {
                $arr[] = "update asterisk.sip set data='$v' where id='" . $this->trunk_prefix . "$n' and keyword='$k';";
            }
            // 如果是注册模式则多写入一条记录
            if ('register' == $data['regMode']) {
                $regstr = sprintf('%s:%s@%s:%d', $data['username'], $data['password'], $data['host'], $data['port']);
                $arr[] = "update asterisk.sip set data='$regstr'  where id='" . $this->register_prefix . "$n' and keyword='register';";
            }
            if ('ims' == $data['regMode']) {
                // +865923750067@ims.fj.chinamobile.com:uzPNBcmPFDjgZyv:865923750067@ims.fj.chinamobile.com@211.143.147.38:5060/+865923750067
                // $regstr = $data['username'] . '@' . $data['fromdomain'] . ':' . $data['password'] . ':' . ltrim($data['username'], '+') . '@' . $data['fromdomain'] . '@' . $data['host'] . ':' . $data['port'] . '/' . $data['username'];
                $regstr = '+' . $data['username'] . ':' . $data['password'] . ':' . $data['username'] . '@' . $data['host'] . ':' . $data['port'] . '/' . $data['fromuser'];
                $arr[] = "update asterisk.sip set data='$regstr'  where id='" . $this->register_prefix . "$n' and keyword='register';";
            }
        } else {
            $list = M('asterisk.sip')->where('keyword=\'account\' and id like \'' . $this->trunk_prefix . '%\'')->max('substr(id,9)+0');
            $n = 2;
            if ($list) {
                $n = $list + 1;
            }
            $i = 2;
            foreach ($sip as $k => $v) {
                $arr[] = "insert into asterisk.sip (id, keyword, data, flags) values ('" . $this->trunk_prefix . "$n','$k','$v',$i);";
                $i++;
            }
            // 如果是注册模式则多写入一条记录
            if ('register' == $data['regMode']) {
                $regstr = sprintf('%s:%s@%s:%d', $data['username'], $data['password'], $data['host'], $data['port']);
                $arr[] = "insert into asterisk.sip (id, keyword, data, flags) values ('" . $this->register_prefix . "$n','register','$regstr',0);";
            }
            if ('ims' == $data['regMode']) {
                // +865923750067@ims.fj.chinamobile.com:uzPNBcmPFDjgZyv:865923750067@ims.fj.chinamobile.com@211.143.147.38:5060/+865923750067
                // $regstr = $data['username'] . '@' . $data['fromdomain'] . ':' . $data['password'] . ':' . ltrim($data['username'], '+') . '@' . $data['fromdomain'] . '@' . $data['host'] . ':' . $data['port'] . '/' . $data['username'];      
                $regstr = '+' . $data['username'] . ':' . $data['password'] . ':' . $data['username'] . '@' . $data['host'] . ':' . $data['port'] . '/' . $data['fromuser'];
                $arr[] = "insert into asterisk.sip (id, keyword, data, flags) values ('" . $this->register_prefix . "$n','register','$regstr',0);";
            }
        }

        // 在globals新增记录
        /*
          $arrglobals = array(
          'OUT_' . $n => 'SIP/' . $data['account'], // SIP/test1
          'OUTPREFIX_' . $n => '',
          'OUTMAXCHANS_' . $n => $data['regNumber'], // 100
          'OUTCID_' . $n => '',
          'OUTKEEPCID_' . $n => 'off', // off
          'OUTFAIL_' . $n => '',
          'OUTDISABLE_' . $n => 'off' // off
          );
          if ($mode == 'update') {
          foreach ($arrglobals as $k => $v) {
          $arr[] = "update asterisk.globals set value='$v' where variable='$k';";
          }
          } else {
          foreach ($arrglobals as $k => $v) {
          $arr[] = "insert into asterisk.globals (variable,value) values ('$k','$v');";
          }
          }
         */
        // 在trunks新增记录
        $params = new \Org\Su\Params();
        $params->addData('name', $data['account']);
        $params->addData('tech', 'sip');
        $params->addData('outcid', '');
        $params->addData('keepcid', 'off');
        $params->addData('maxchans', $data['regNumber']);
        $params->addData('failscript', '');
        $params->addData('dialoutprefix', '');
        $params->addData('channelid', $data['account']);
        $params->addData('usercontext', '');
        $params->addData('provider', '');
        $params->addData('disabled', 'off');
        $params->addData('continue', 'off');
        if ($mode == 'update') {
            $arr[] = $params->get_update_sql('asterisk.trunks', 'name=\'' . $data['account'] . '\'');
        } else {
            $params->addData('trunkid', $n);
            $arr[] = $params->get_insert_sql('asterisk.trunks');
        }
        return $arr;
    }

    protected function Activate($data, $activated = true) {
        if (!$data) {
            return '数据有误!';
        }
        $msg = $this->save_to_additional($data, $activated);
        if ($msg === true) {
            $this->save_to_registrations($data, $activated);
        }
        return $msg;
    }

    protected function save_to_additional($data, $activated = true) {
        if (!$data) {
            return '数据有误!';
        }
        if (!file_exists(sip_additional_path)) {
            return 'IP配置文件不存在!';
        }
        if (!is_writable(sip_additional_path)) {
            return 'IP配置文件不允许读写!';
        }

        $file_content = file_get_contents(sip_additional_path);
        if ($activated) {
            if (strstr($file_content, '[' . $data['account'] . ']')) {
                return 'IP配置文件中已包含此分机';
            }
            if ('ip' == $data['regMode']) {
                $content = sip_additional_ip_tpl;
            } else {
                $content = sip_additional_reg_tpl;
            }
            $content = str_replace("{trunk}", $data["username"], $content);
            $content = str_replace("{host}", $data["host"], $content);
            $content = str_replace("{port}", $data["port"], $content);
            $content = str_replace("{defaultexpiry}", $data["defaultexpiry"], $content);
            if ('register' == $data['regMode'] || 'ims' == $data['regMode']) {
                $content = str_replace("{fromdomain}", $data["fromdomain"], $content);
                $content = str_replace("{username}", $data["username"], $content);
                $content = str_replace("{fromuser}", $data["fromuser"], $content);
                $content = str_replace("{secret}", $data["password"], $content);
                $content = str_replace("{insecure}", $data['insecure'], $content);
            }
            $content = str_replace("{context}", $data['context'], $content);
            $content = str_replace("{dtmfmode}", $data['dtmfmode'], $content);
            $strallow = '';
            if ($data['allow']) {
                $arrallow = explode(',', $data['allow']);
                foreach ($arrallow as $v) {
                    $strallow .= 'allow=' . $v . '\n';
                }
                $strallow = substr($strallow, 0, strlen($strallow) - 2);
            }
            $content = str_replace("{allow}", $strallow, $content);
            $content = str_replace("{nat}", $data['nat'], $content);
            $content = str_replace("{type}", $data['type'], $content);
            $content = str_replace("{disallow}", $data['disallow'], $content);
            $fp = fopen(sip_additional_path, 'a+');
            fwrite($fp, $content);
            fclose($fp);
        } else {
            if (strstr($file_content, '[' . $data['account'] . ']')) {
                $file_content = ereg_replace('\[' . $data['account'] . '[^\[]*[^\[]?', "", $file_content);
                file_put_contents(sip_additional_path, $file_content);
            }
        }
        return true;
    }

    protected function save_to_registrations($data, $activated = true) {
        if (!$data) {
            return '数据有误!';
        }
        if (!file_exists(sip_registrations_path)) {
            return '注册模式配置文件不存在!';
        }
        if (!is_writable(sip_registrations_path)) {
            return '注册模式配置文件不允许读写!';
        }

        $file_content = file_get_contents(sip_registrations_path);
        if ($activated && 'register' == $data['regMode']) {
            if (strstr($file_content, '\n\n' . $data['username'] . ':')) {
                return '注册模式配置文件中已包含此用户名!';
            }
            $content = sip_trunk_reg_tpl;
            $content = str_replace("{host}", $data["host"], $content);
            $content = str_replace("{port}", $data["port"], $content);
            $content = str_replace("{username}", $data["username"], $content);
            $content = str_replace("{secret}", $data["password"], $content);
            $fp = fopen(sip_registrations_path, 'a+');
            fwrite($fp, $content);
            fclose($fp);
        } else {
            if (strstr($file_content, 'register=' . $data['username'] . ':')) {
                $file_content = ereg_replace('register=' . $data['username'] . '[^\n]*[^\n]?', "", $file_content);
                file_put_contents(sip_registrations_path, $file_content);
            }
        }
        return true;
    }

}
